# @Time : 2021/5/14 11:42
# @Author : Fioman 
# @Phone : 13149920693
import json
import shutil
from datetime import datetime

import cv2 as cv

import settings
from app.datetime_helper import get_datetime_for_logger_dir
from settings import *
from tools.common_tools import get_time_now_string
from tools.hd_logger import HdLogger

"""
将图片保存进电脑设备中的模块,这个模块主要用来保存设备中的图片.包括标定的时候,或者是其他的时候的图片一并保存进来.
"""
logger = HdLogger()


def remove_old_dirs_by_name(root_dir):
    """
    根据目录名中的日期清理旧目录
    :param root_dir: 根目录路径（如 D:\raw）
    """
    try:
        now = datetime.now()
        # 遍历根目录下所有子目录
        for dir_name in os.listdir(root_dir):
            dir_path = os.path.join(root_dir, dir_name)
            if not os.path.isdir(dir_path):
                continue  # 跳过非目录

            # 尝试解析目录名为日期（格式：YYYY-MM-DD）
            try:
                dir_date = datetime.strptime(dir_name, "%Y-%m-%d")
            except ValueError:
                continue  # 忽略不符合格式的目录

            # 计算日期差
            delta = now - dir_date
            from tools.config_params import ConfigParams
            cp = ConfigParams()
            if delta.days >= cp.imgKeepDays:
                try:
                    shutil.rmtree(dir_path)
                    logger.debug(f"已删除旧目录: {dir_path}")
                except Exception as e:
                    logger.debug(f"删除目录失败: {dir_path}, 错误: {str(e)}")
    except Exception as e:
        logger.debug(f"清理旧目录时发生错误: {str(e)}")


def create_image_dir_by_order_id(order_id, joint_number):
    """
    根据工单Id创建生产作业使用的图像目录
    """
    dir_list = []
    root_dir = r"D:\raw"
    remove_old_dirs_by_name(root_dir)
    root_dir = os.path.join(root_dir, r"{}\{}\{}pin".format(
        get_datetime_for_logger_dir(), order_id, joint_number))
    if joint_number == "2":
        settings.first_cut_board_dir_2pin = os.path.join(root_dir, r"first_cut")
        dir_list.append(settings.first_cut_board_dir_2pin)
        settings.size_check_ok_dir_2pin = os.path.join(root_dir, r"first_cut\size_check_ok")
        dir_list.append(settings.size_check_ok_dir_2pin)
        settings.raw_ok_dir_2pin = os.path.join(root_dir, r"raw_ok")
        dir_list.append(settings.raw_ok_dir_2pin)
        settings.raw_cut_dir_2pin = os.path.join(root_dir, r"raw_cut")
        dir_list.append(settings.raw_cut_dir_2pin)
        settings.totalboard_error_dir_2pin = os.path.join(root_dir, r"totalboard_error")
        dir_list.append(settings.totalboard_error_dir_2pin)
        settings.raw_fail_dir_2pin = os.path.join(root_dir, r"raw_fail")
        dir_list.append(settings.raw_fail_dir_2pin)
    else:
        settings.first_cut_board_dir_1pin = os.path.join(root_dir, r"first_cut")
        dir_list.append(settings.first_cut_board_dir_1pin)
        settings.size_check_ok_dir_1pin = os.path.join(root_dir, r"first_cut\size_check_ok")
        dir_list.append(settings.size_check_ok_dir_1pin)
        settings.raw_ok_dir_1pin = os.path.join(root_dir, r"raw_ok")
        dir_list.append(settings.raw_ok_dir_1pin)
        settings.raw_cut_dir_1pin = os.path.join(root_dir, r"raw_cut")
        dir_list.append(settings.raw_cut_dir_1pin)
        settings.totalboard_error_dir_1pin = os.path.join(root_dir, r"totalboard_error")
        dir_list.append(settings.totalboard_error_dir_1pin)
        settings.raw_fail_dir_1pin = os.path.join(root_dir, r"raw_fail")
        dir_list.append(settings.raw_fail_dir_1pin)

    cutter_dir = r"D:\cutter_raw"
    remove_old_dirs_by_name(cutter_dir)
    cutter_dir = os.path.join(cutter_dir, r"{}\{}".format(get_datetime_for_logger_dir(), order_id))
    settings.cutter_raw_begin_dir = os.path.join(cutter_dir, "begin_check")
    dir_list.append(settings.cutter_raw_begin_dir)
    settings.cutter_raw_begin_res_dir = os.path.join(cutter_dir, "begin_check_res")
    dir_list.append(settings.cutter_raw_begin_res_dir)
    settings.cutter_raw_final_dir = os.path.join(cutter_dir, "final_check")
    dir_list.append(settings.cutter_raw_final_dir)
    settings.cutter_raw_final_res_dir = os.path.join(cutter_dir, "final_check_res")
    dir_list.append(settings.cutter_raw_final_res_dir)

    try:
        for file_dir in dir_list:
            if not os.path.exists(file_dir):
                os.makedirs(file_dir)
    except Exception as e:
        logger.debug(f"in  create_image_dir_by_order_id() error: {str(e)}")


def save_cutter_cam_cal_image(keepIndex, image, endWith="original"):
    """
    保存铡刀标定的时候的图片,铡刀标定的时候的图片保存,标定的原图,还有结果图都要保存.
    :param keepIndex:要保存的图像编号
    :param image:要保存的图片
    :param endWith:是否加后缀,比如有的图片加个res比较好
    :return:
    """
    try:
        keepDir = CUTTER_CAM_CAL_DIR
        fileName = "{}--{}--{}.bmp".format(keepIndex, get_time_now_string(), endWith)
        cv.imwrite(os.path.join(keepDir, fileName), image)
    except Exception as e:
        errorInfo = "in save_cutter_cam_cal_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def delete_exist_index_image(keepDir, boardIndex):
    """
    遍历保存图像的目录,删除将要保存的相同id的图片
    :param keepDir:图片保存目录
    :param boardIndex:图像id序列号
    :return:
    """
    for root, dirs, files in os.walk(keepDir):
        for file in files:
            try:
                index = file.split('--')[0]
                if index == str(boardIndex):
                    os.remove(os.path.join(root, file))
            except Exception as e:
                print(str(e))


def delete_exist_index_image_for_cutter(keepDir, boardIndex):
    """
    遍历保存图像的目录,删除将要保存的相同id的图片
    :param keepDir:图片保存目录
    :param boardIndex:图像id序列号
    :return:
    """
    for root, dirs, files in os.walk(keepDir):
        for file in files:
            try:
                index = file.split('--')[0]
                if int(index) % 1000 == int(boardIndex) % 1000:
                    os.remove(os.path.join(root, file))
            except Exception as e:
                print(str(e))


def save_totalboard_error_image(keepIndex, imageOriginal, imageRes, jointNumber):
    """
    保存物料检测未通过的图片
    :param keepIndex: 图片的索引
    :param imageOriginal: 原图
    :param imageRes: 识别的结果图
    :return:
    """
    try:
        if jointNumber == "2":
            dirUsed = settings.totalboard_error_dir_2pin
        elif jointNumber == "3":
            dirUsed = settings.totalboard_error_dir_2pin
        else:
            dirUsed = settings.totalboard_error_dir_1pin

        delete_exist_index_image(dirUsed, keepIndex)
        fileNameOriginal = "{}--{}--orginal.bmp".format(keepIndex, get_time_now_string())
        fileNameRes = "{}--{}--res.bmp".format(keepIndex, get_time_now_string())
        cv.imwrite(os.path.join(dirUsed, fileNameOriginal), imageOriginal)
        cv.imwrite(os.path.join(dirUsed, fileNameRes), imageRes)
    except Exception as e:
        errorInfo = "in save_totalBoard_error_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_three_totalboard_error_image(keepIndex, imageOriginal, imageRes):
    """
    保存三拼物料检测未通过的图片
    :param keepIndex: 图片的索引
    :param imageOriginal: 原图
    :param imageRes: 识别的结果图
    :return:
    """
    try:
        delete_exist_index_image(settings.totalboard_error_dir_2pin, keepIndex)
        fileNameOriginal = "{}--{}--orginal.bmp".format(keepIndex, get_time_now_string())
        fileNameRes = "{}--{}--res.bmp".format(keepIndex, get_time_now_string())
        cv.imwrite(os.path.join(settings.totalboard_error_dir_2pin, fileNameOriginal), imageOriginal)
        cv.imwrite(os.path.join(settings.totalboard_error_dir_2pin, fileNameRes), imageRes)
    except Exception as e:
        errorInfo = "in save_three_totalboard_error_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_calc_ok_image(keepIndex, keepImage, widthPix, heightPix, jointNumber, layoutMode="竖排"):
    """
    保存首板的图,并且保存切线的位置信息.
    :param keepIndex:保存的图像编号
    :param keepImage:要保存到额图像
    :param widthPix:图像宽度像素值
    :param heightPix:图像高度像素值
    :param upLineOffset:上框位置
    :param downLineOffset:下框位置
    :return:
    """
    try:
        if jointNumber == "2":
            keepDir = settings.raw_ok_dir_2pin
        else:
            keepDir = settings.raw_ok_dir_1pin
        if layoutMode == "竖排":
            endWith = "sp"  # 首板尺寸确认保存的图片
        else:
            endWith = "hp"
        delete_exist_index_image(keepDir, keepIndex)
        fileName = f"{keepIndex}--{get_time_now_string()}--w_{widthPix}--h_{heightPix}--{endWith}.bmp"
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_calc_ok_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_three_calc_ok_image(keepIndex, keepImage, widthPix, heightPix, layoutMode="竖排"):
    """
    保存三拼首板的图,并且保存切线的位置信息.
    :param keepIndex:保存的图像编号
    :param keepImage:要保存到额图像
    :param widthPix:图像宽度像素值
    :param heightPix:图像高度像素值
    :param upLineOffset:上框位置
    :param downLineOffset:下框位置
    :return:
    """
    try:
        if layoutMode == "竖排":
            endWith = "sp"  # 首板尺寸确认保存的图片
        else:
            endWith = "hp"
        keepDir = settings.raw_ok_dir_2pin
        delete_exist_index_image(keepDir, keepIndex)
        fileName = f"{keepIndex}--{get_time_now_string()}--w_{widthPix}--h_{heightPix}--{endWith}.bmp"
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_size_is_ok_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_one_calc_ok_image(keepIndex, keepImage, widthPix, heightPix, layoutMode="竖排"):
    """
    保存三拼首板的图,并且保存切线的位置信息.
    :param keepIndex:保存的图像编号
    :param keepImage:要保存到额图像
    :param widthPix:图像宽度像素值
    :param heightPix:图像高度像素值
    :param upLineOffset:上框位置
    :param downLineOffset:下框位置
    :return:
    """
    try:
        if layoutMode == "竖排":
            endWith = "sp"  # 首板尺寸确认保存的图片
        else:
            endWith = "hp"
        keepDir = settings.raw_ok_dir_1pin
        delete_exist_index_image(keepDir, keepIndex)
        fileName = f"{keepIndex}--{get_time_now_string()}--w_{widthPix}--h_{heightPix}--{endWith}.bmp"
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_size_is_ok_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_cut_line_image(keepIndex, keepImage, widthPix, heightPix, endwith="calc", layoutMode="竖排", jointNumber="2"):
    """
    保存切线图,高和宽各自缩放两倍
    :param keepIndex: 保存的图像编号
    :param keepImage: 要保存的图像
    :param widthPix: 宽度像素值
    :param heightPix: 高度像素值
    :param endwith: 是识别出来的,还是标注的图
    :return:
    """
    try:
        if layoutMode == "竖排":
            endwith += "sp"  # 首板尺寸确认保存的图片
        else:
            endwith += "hp"
        if jointNumber == "2":
            keepDir = settings.raw_cut_dir_2pin
        else:
            keepDir = settings.raw_cut_dir_1pin
        delete_exist_index_image(keepDir, keepIndex)
        sizeScale = 2
        newWidth, newHeight = keepImage.shape[1] // sizeScale, keepImage.shape[0] // sizeScale
        keepImage = cv.resize(keepImage.copy(), (newWidth, newHeight), cv.INTER_AREA)
        fileName = "{}--{}--w_{}--h_{}--{}.bmp".format(keepIndex, get_time_now_string(), widthPix, heightPix, endwith)
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_cut_line_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_three_cut_line_image(keepIndex, keepImage, widthPix, heightPix, endwith="calc", isFanzhuan="否"):
    """
    保存三拼切线图,高和宽各自缩放两倍
    :param keepIndex: 保存的图像编号
    :param keepImage: 要保存的图像
    :param widthPix: 宽度像素值
    :param heightPix: 高度像素值
    :param endwith: 是识别出来的,还是标注的图
    :return:
    """
    try:
        if isFanzhuan == "否":
            keepDir = raw_cut_dir_2pin  # 首板尺寸确认保存的图片
        else:
            keepDir = raw_cut_dir_2pin
        delete_exist_index_image(keepDir, keepIndex)
        sizeScale = 2
        newWidth, newHeight = keepImage.shape[1] // sizeScale, keepImage.shape[0] // sizeScale
        keepImage = cv.resize(keepImage.copy(), (newWidth, newHeight), cv.INTER_AREA)
        fileName = "{}--{}--w_{}--h_{}--{}.bmp".format(keepIndex, get_time_now_string(), widthPix, heightPix, endwith)
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_cut_line_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_one_cut_line_image(keepIndex, keepImage, widthPix, heightPix, endwith="calc", layoutMode="竖排"):
    """
    保存三拼切线图,高和宽各自缩放两倍
    :param keepIndex: 保存的图像编号
    :param keepImage: 要保存的图像
    :param widthPix: 宽度像素值
    :param heightPix: 高度像素值
    :param endwith: 是识别出来的,还是标注的图
    :return:
    """
    try:
        if layoutMode == "竖排":
            endwith += "sp"
        else:
            endwith += "hp"
        keepDir = settings.raw_ok_dir_1pin
        delete_exist_index_image(keepDir, keepIndex)
        sizeScale = 2
        newWidth, newHeight = keepImage.shape[1] // sizeScale, keepImage.shape[0] // sizeScale
        keepImage = cv.resize(keepImage.copy(), (newWidth, newHeight), cv.INTER_AREA)
        fileName = "{}--{}--w_{}--h_{}--{}.bmp".format(keepIndex, get_time_now_string(), widthPix, heightPix, endwith)
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_cut_line_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_calc_error_image(keepIndex, keepImage, widthPix, heightPix, jointNumber="2", layoutMode="竖排"):
    """
    保存失败的图,并且保存切线的位置信息.
    :param keepIndex:保存的图像编号
    :param keepImage:要保存到额图像
    :param widthPix:图像宽度像素值
    :param heightPix:图像高度像素值
    :param upLineOffset:上框位置
    :param downLineOffset:下框位置
    :return:
    """
    try:
        if layoutMode == "竖排":
            endwith = "sp"  # 首板尺寸确认保存的图片
        else:
            endwith = "hp"
        if jointNumber == "2":
            keepDir = settings.raw_ok_dir_2pin
        else:
            keepDir = settings.raw_ok_dir_1pin
        delete_exist_index_image(keepDir, keepIndex)
        fileName = f"{keepIndex}--{get_time_now_string()}--w_{widthPix}--h_{heightPix}--{endwith}.bmp"
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_size_is_ok_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_three_calc_error_image(keepIndex, keepImage, widthPix, heightPix, upLineOffset, downLineOffset, isFanzhuan="否"):
    """
    保存失败的图,并且保存切线的位置信息.
    :param keepIndex:保存的图像编号
    :param keepImage:要保存到额图像
    :param widthPix:图像宽度像素值
    :param heightPix:图像高度像素值
    :param upLineOffset:上框位置
    :param downLineOffset:下框位置
    :return:
    """
    try:
        if isFanzhuan == "否":
            keepDir = raw_fail_dir_2pin  # 首板尺寸确认保存的图片
        else:
            keepDir = raw_fail_dir_2pin
        delete_exist_index_image(keepDir, keepIndex)
        fileName = "{}--{}--w_{}--h_{}--u_{}_{}_{}_{}--d_{}_{}_{}_{}.bmp".format(keepIndex, get_time_now_string(), widthPix, heightPix,
                                                                                 upLineOffset[0], upLineOffset[1], upLineOffset[2], upLineOffset[3],
                                                                                 downLineOffset[0], downLineOffset[1], downLineOffset[2],
                                                                                 downLineOffset[3])
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_size_is_ok_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_one_calc_error_image(keepIndex, keepImage, widthPix, heightPix, layoutMode="竖排"):
    """
    保存三拼首板的图,并且保存切线的位置信息.
    :param keepIndex:保存的图像编号
    :param keepImage:要保存到额图像
    :param widthPix:图像宽度像素值
    :param heightPix:图像高度像素值
    :param upLineOffset:上框位置
    :param downLineOffset:下框位置
    :return:
    """
    try:
        if layoutMode == "竖排":
            endWith = "sp"  # 首板尺寸确认保存的图片
        else:
            endWith = "hp"
        keepDir = settings.raw_fail_dir_1pin
        delete_exist_index_image(keepDir, keepIndex)
        fileName = f"{keepIndex}--{get_time_now_string()}--w_{widthPix}--h_{heightPix}--{endWith}.bmp"
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_size_is_ok_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_final_check_image(keepIndex, image1, image2):
    """
    保存终点检测的图片
    :param keepIndex:保存的图像编号
    :param image1: 1号相机的图
    :param image2: 2号相机的图
    :return:
    """
    try:
        keepDir = settings.cutter_raw_final_dir  # 首板尺寸确认保存的图片
        delete_exist_index_image_for_cutter(keepDir, keepIndex)
        fileName = "{}--{}--final_cam1.bmp".format(keepIndex, get_time_now_string())
        cv.imwrite(os.path.join(keepDir, fileName), image1)
        fileName = "{}--{}--final_cam2.bmp".format(keepIndex, get_time_now_string())
        cv.imwrite(os.path.join(keepDir, fileName), image2)
    except Exception as e:
        errorInfo = "in save_final_check_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_three_final_check_image(keepIndex, image1, image2):
    """
    保存终点检测的图片
    :param keepIndex:保存的图像编号
    :param image1: 1号相机的图
    :param image2: 2号相机的图
    :return:
    """
    try:
        keepDir = settings.cutter_raw_final_dir  # 首板尺寸确认保存的图片
        delete_exist_index_image_for_cutter(keepDir, keepIndex)
        fileName = "{}--{}--final_cam1.bmp".format(keepIndex, get_time_now_string())
        cv.imwrite(os.path.join(keepDir, fileName), image1)
        fileName = "{}--{}--final_cam2.bmp".format(keepIndex, get_time_now_string())
        cv.imwrite(os.path.join(keepDir, fileName), image2)
    except Exception as e:
        errorInfo = "in save_final_check_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_final_check_image_res(keepIndex, image1, image2):
    """
    保存终点检测的图片
    :param keepIndex:保存的图像编号
    :param image1: 1号相机的图
    :param image2: 2号相机的图
    :return:
    """
    try:
        keepDir = settings.cutter_raw_final_res_dir  # 首板尺寸确认保存的图片
        delete_exist_index_image_for_cutter(keepDir, keepIndex)
        scale = 3
        keepImage1 = cv.resize(image1.copy(), (image1.shape[1] // scale, image1.shape[0] // scale), cv.INTER_AREA)
        keepImage2 = cv.resize(image2.copy(), (image2.shape[1] // scale, image2.shape[0] // scale), cv.INTER_AREA)
        fileName = "{}--{}--final_res_cam1.bmp".format(keepIndex, get_time_now_string())
        cv.imwrite(os.path.join(keepDir, fileName), keepImage1)
        fileName = "{}--{}--final_res_cam2.bmp".format(keepIndex, get_time_now_string())
        cv.imwrite(os.path.join(keepDir, fileName), keepImage2)
    except Exception as e:
        errorInfo = "in save_final_check_image_res() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_three_final_check_image_res(keepIndex, image1, image2):
    """
    保存终点检测的图片
    :param keepIndex:保存的图像编号
    :param image1: 1号相机的图
    :param image2: 2号相机的图
    :return:
    """
    try:
        keepDir = cutter_raw_final_res_dir  # 首板尺寸确认保存的图片
        delete_exist_index_image_for_cutter(keepDir, keepIndex)
        scale = 3
        keepImage1 = cv.resize(image1.copy(), (image1.shape[1] // scale, image1.shape[0] // scale), cv.INTER_AREA)
        keepImage2 = cv.resize(image2.copy(), (image2.shape[1] // scale, image2.shape[0] // scale), cv.INTER_AREA)
        fileName = "{}--{}--final_res_cam1.bmp".format(keepIndex, get_time_now_string())
        cv.imwrite(os.path.join(keepDir, fileName), keepImage1)
        fileName = "{}--{}--final_res_cam2.bmp".format(keepIndex, get_time_now_string())
        cv.imwrite(os.path.join(keepDir, fileName), keepImage2)
    except Exception as e:
        errorInfo = "in save_final_check_image_res() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_begin_check_image(keepIndex, keepImage, endwith="first"):
    """
    保存铡刀起点检测的图片
    :param keepIndex:
    :param keepImage:
    :param endwith:
    :return:
    """
    try:
        keepDir = settings.cutter_raw_begin_dir  # 首板尺寸确认保存的图片
        delete_exist_index_image_for_cutter(keepDir, keepIndex)
        fileName = "{}--{}--{}.bmp".format(keepIndex, get_time_now_string(), endwith)
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_size_is_ok_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_begin_check_res_image(keepIndex, keepImage, endwith="first"):
    """
    保存铡刀起点检测的结果图片
    :param keepIndex:
    :param keepImage:
    :param endwith:
    :return:
    """
    try:
        keepDir = settings.cutter_raw_begin_res_dir  # 首板尺寸确认保存的图片
        delete_exist_index_image_for_cutter(keepDir, keepIndex)
        fileName = "{}--{}--{}.bmp".format(keepIndex, get_time_now_string(), endwith)
        scale = 3
        keepImage = cv.resize(keepImage.copy(), (keepImage.shape[1] // scale, keepImage.shape[0] // scale), cv.INTER_AREA)
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_size_is_ok_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_first_board_cut_image(keepIndex, keepImage, widthPix, heightPix, endwith="calc", jointNumber="2", layoutMode="竖排"):
    try:
        if layoutMode == "竖排":
            endwith += "sp"
        else:
            endwith += "hp"
        if jointNumber == "2":
            keepDir = settings.first_cut_board_dir_2pin
        else:
            keepDir = settings.first_cut_board_dir_1pin
        delete_exist_index_image(keepDir, keepIndex)
        fileName = "{}--{}--w_{}--h_{}--{}.bmp".format(keepIndex, get_time_now_string(), widthPix, heightPix, endwith)
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_size_is_ok_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def save_size_is_ok_image(keepIndex, keepImage, widthPix, heightPix, endWith="calc",
                          jointNumber="2", layoutMode="竖排"):
    """
    @param keepIndex:
    @param keepImage:
    @param widthPix:
    @param heightPix:
    @param endWith:
    @param jointNumber:
    @param layoutMode:
    """
    try:
        if layoutMode == "竖排":
            endWith += "sp"
        else:
            endWith += "hp"
        if jointNumber == "2":
            keepDir = settings.size_check_ok_dir_2pin
        else:
            keepDir = settings.size_check_ok_dir_1pin
        delete_exist_index_image(keepDir, keepIndex)
        fileName = "{}--{}--w_{}--h_{}--{}.bmp".format(keepIndex, get_time_now_string(),
                                                       widthPix, heightPix, endWith)
        cv.imwrite(os.path.join(keepDir, fileName), keepImage)
    except Exception as e:
        errorInfo = "in save_size_is_ok_image() error:{}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


# def save_train_dataset(upBox, downBox, totalBoard, fileName):
#     """
#     保存人工智能训练队额图片
#     :param upBox: 上框位置信息
#     :param downBox: 下框位置信息
#     :param totalBoard: 整个物料图
#     :param fileName: 文件名称
#     :return:
#     """
#     keepDir = TRAIN_DATASET_DIR
#     keepColorDir = os.path.join(TRAIN_DATASET_DIR, "train_dataset_jd_color")  # 保存那些画线了的dir
#     if not os.path.exists(keepDir):
#         os.mkdir(keepDir)
#     if not os.path.exists(keepColorDir) and DEVELOP:
#         os.mkdir(keepColorDir)
#     boardHeight = totalBoard.shape[0]
#     bigHalfSize = int(boardHeight * 0.55)
#     upBoard = totalBoard[:bigHalfSize]
#     downBoard = totalBoard[-bigHalfSize:]
#
#     # 高大于宽,右侧补零,size用高,否则size用宽,最后要得到的结果是一个正方形
#     upSize = max(upBoard.shape)
#     padUp = np.zeros((upSize, upSize), dtype='uint8')
#     padUp[:upBoard.shape[0], :upBoard.shape[1]] = upBoard  # 将原来的图片补充上来,然后剩余的地方补充为黑色,得到上面的图.
#
#     downSize = max(downBoard.shape)
#     padDown = np.zeros((downSize, downSize), dtype='uint8')
#     padDown[:downBoard.shape[0], :downBoard.shape[1]] = downBoard
#
#     # 得到了上下的两张图.
#     upBox = np.array(upBox).astype('int')  # 大图上的坐标,这里可以不变,因为截取完之后,上面的图的坐标并没有变化
#     downBox = (np.array(downBox) - (0, (totalBoard.shape[0] - bigHalfSize))).astype('int')  # 这里要把大图上的坐标,转换为小图上,所有的y都要减去一个数.矩阵操作.坐标y值,会以此减去后面的值.
#
#     # 获取上面矩形的一些信息
#     upRect = cv.minAreaRect(upBox)
#     (upCenterX, upCenterY), (upWidth, upHeight), upAngle = upRect
#     upAngle = 90 + upAngle if upAngle < -70 else upAngle  # 调整 angle
#
#     downRect = cv.minAreaRect(downBox)
#     (downCenterX, downCenterY), (downWidth, downHeight), downAngle = downRect
#     downAngle = 90 + downAngle if downAngle < -70 else downAngle  # 调整angle
#
#     # 将用来训练的识别的结果保存到json文件当中去.
#     upRectJson = [upCenterX / upSize, upCenterY / upSize, upWidth / upSize, upHeight / upSize, upAngle]
#     downRectJson = [downCenterX / downSize, downCenterY / downSize, downWidth / downSize, downHeight / downSize, downAngle]
#
#     upBoxJson = upBox / upSize
#     downBoxJson = downBox / downSize
#
#     # 然后是画出轮廓以及保存图片
#     # 准备画布,转换为三通道彩色图片,以便于画出轮廓线
#     if DEVELOP:
#         upPoints = np.int0(cv.boxPoints(upRect))
#         downPoints = np.int0(cv.boxPoints(downRect))
#         upImageColor = cv.cvtColor(padUp, cv.COLOR_GRAY2BGR)
#         downImageColor = cv.cvtColor(padDown, cv.COLOR_GRAY2BGR)
#         cv.drawContours(upImageColor, [upPoints], 0, (0, 255, 0), 3)
#         cv.drawContours(downImageColor, [downPoints], 0, (0, 255, 0), 3)
#         # 将彩色图片保存到文件中.如果是开发者模式
#         cv.imwrite(os.path.join(keepColorDir, fileName[:-4] + "_up.bmp"), cv.resize(upImageColor, (500, 500)))
#         cv.imwrite(os.path.join(keepColorDir, fileName[:-4] + "_down.bmp"), cv.resize(downImageColor, (500, 500)))
#     # 将图片分别保存到目标文件中
#     cv.imwrite(os.path.join(keepDir, fileName[:-4] + "_up.bmp"), cv.resize(padUp, (500, 500)))
#     cv.imwrite(os.path.join(keepDir, fileName[:-4] + "_down.bmp"), cv.resize(padDown, (500, 500)))
#
#     # 将板的信息写入到json文件中
#     save_single_board_res(keepDir, "singles.json", fileName[:-4], upBoxJson.tolist(), downBoxJson.tolist(), upRectJson, downRectJson)


def save_single_board_res(keepDir, jsonName, fileName, upPoints, downPoints, upRect, downRect):
    """
    保存单个板的信息,将板的信息保存起来,保存为json文件,用作后面的训练.
    :param keepDir: 保存json文件的根目录
    :param jsonName: json文件的名称
    :param fileName: 图片的名称
    :param upPoints:   在原来的整块图像上的上板四个顶点坐标
    :param downPoints: 在原来的整块图像上的下板的四个顶点坐标
    :param upRect:  在新的训练图上 上板的矩形框的位置信息,包括中心点,长宽,以及角度,除了角度都用用百分比进行表示的.
    :param downRect:在新的训练图上 下板的矩形框的位置信息,包括中心点,长宽,以及角度,除了角度都是用百分比进行表示的.
    :return:
    """
    jsonPath = os.path.join(keepDir, jsonName)
    firstKeep = False
    if not os.path.exists(jsonPath):  # 如果文件不存在就创建
        with open(jsonPath, "w") as f:
            firstKeep = True
            f.close()
    data = {}
    try:
        with open(jsonPath, "r") as f:
            if not firstKeep:  # 如果不是第一次保存
                data = json.load(f)  # 通过json加载文件
            data[fileName + "_up.bmp"] = {
                "points": upPoints,
                "rect": upRect,
            }
            data[fileName + "down.bmp"] = {
                "points": downPoints,
                "rect": downRect,
            }
        with open(jsonPath, "w") as f:  # 注意python中没有rw模式,也就是既可以读又可以写的模式.
            json.dump(data, f)  # 数据写入到文件中.
    except Exception as e:
        errorInfo = "in save_single_board_res() error: {}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)


def delete_total_cutter_cal_image():
    """
    删除所有的标定用图片
    :return:
    """
    deleteDir = CUTTER_CAM_CAL_DIR
    try:
        for root, dirs, files in os.walk(deleteDir):
            for file in files:
                os.remove(os.path.join(root, file))
    except Exception as e:
        errorInfo = "in delete_total_cutter_cal_image() error: {}".format(str(e))
        print(errorInfo)
        logger.debug(errorInfo)
        return errorInfo
    return "ok"


def open_cutter_cam_cal_dir():
    """
    打开铡刀标定时的图片目录
    :return:
    """
    ret = os.system("explorer.exe {}".format(CUTTER_CAM_CAL_DIR))
    return "ok" if ret == 1 else ret


def open_count_board_size_dir():
    """
    打开用于计算和统计物料宽高的目录
    :return:
    """
    ret = os.system("explorer.exe {}".format(COUNT_BOARD_SIZE_DIR))
    return "ok" if ret == 1 else ret


def open_line_cam_cal_image_dir():
    """
    打开线阵相机标定点额目录
    :return:
    """
    ret = os.system("explorer.exe {}".format(CALIBRATION_DIR))
    return "ok" if ret == 1 else ret


def open_debug_dir():
    """
    打开日志文件的目录
    :return:
    """
    ret = os.system("explorer.exe {}".format(DEBUG_DIR))
    return "ok" if ret == 1 else ret


def open_dir_by_file_path(openDir):
    """
    根据要打开的目录路径,打开某个目录.
    :param openDir: 要打开的目录路径
    :return:
    """
    ret = os.system("explorer.exe {}".format(openDir))
    return "ok" if ret == 1 else ret


def get_image_index_by_path(imagePath):
    """
    根据图像目录,获取所有的图像编号
    :param imagePath: 图像的目录
    :return:
    """
    if not os.path.exists(imagePath):
        return []
    fileNames = []
    for root, dirs, files in os.walk(imagePath):
        for file in files:
            if root != imagePath:
                continue
            if file[-4:] != ".bmp":
                continue
            fileNames.append(file)

    indexList = []
    for fileName in fileNames:
        if "--" in fileName:
            indexFinded = fileName.split("--")[0]
            timeFinded = fileName.split("--")[1]
            indexList.append(indexFinded + "--" + timeFinded)
    return indexList


def get_image_by_image_path_and_image_index(findPath, indexTimeStr):
    """
    根据文件路径以及图像编号和时间去获取图片.
    :param findPath: 遍历的目录
    :param indexTimeStr: 图片名称,包含图像编号和时间的字符串.
    :return:
    """
    if not os.path.exists(findPath):
        return False, "查找的目录不存在", indexTimeStr
    fileNames = []
    for root, dirs, files in os.walk(findPath):
        for file in files:
            if root != findPath:
                continue
            if file[-4:] != ".bmp":
                continue
            fileNames.append(file)

    imageFinded = [fileName for fileName in fileNames if indexTimeStr in fileName]
    if len(imageFinded) > 0:
        imageNameFinded = imageFinded[0]
        filePath = os.path.join(findPath, imageNameFinded)
        image = cv.imread(filePath)
        return True, image, imageNameFinded
    else:
        return False, "{}的图像找不到".format(indexTimeStr), indexTimeStr


def open_database_dump_dir():
    """
    打开数据库备份的目录
    :return:
    """
    openDir = DATA_BASE_DUMP_DIR
    ret = os.system("explorer.exe {}".format(openDir))
    return "ok" if ret == 1 else ret


def open_database_import_dir():
    """
    打开数据库导入的目录
    :return:
    """
    openDir = DATA_BASE_IMPORT_DIR
    ret = os.system("explorer.exe {}".format(openDir))
    return "ok" if ret == 1 else ret
